home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 425_01 / tar / savefile.c < prev    next >
Text File  |  1980-07-23  |  11KB  |  399 lines

  1. /* savefile.c - storying regular files into (tape) archive
  2.  * This is the part of the Tar program (see file tar.c)
  3.  * Author: T.V.Shaporev
  4.  * Creation date 11 Mar 1993
  5.  */
  6. #include <stdio.h>
  7.  
  8. #include "sysup.h"
  9. #include "modern.h"
  10. #include "compress.h"
  11. #include "define.h"
  12.  
  13. extern char longname[];
  14.  
  15. extern void proctl  __ARGS__(( char *, long ));
  16. extern void prcsum  __ARGS__(( register struct header * ));
  17. extern void newhead __ARGS__(( char *, long ));
  18. extern char *deleft __ARGS__(( char * ));
  19.  
  20. #ifdef UNIX
  21.     static werelost = FALSE;
  22. #endif
  23.  
  24. #ifdef MSDOS
  25. #    include <string.h>
  26. #    ifdef __TURBOC__
  27. #        include <dir.h>
  28. #    else
  29. #        include <direct.h>
  30. #    endif
  31. #    include <io.h>
  32.  
  33. static int skipdots __ARGS__(( char *, int ));
  34. static int unperiod __ARGS__(( char *, int ));
  35. static int nextchar __ARGS__(( char *, int ));
  36.  
  37. static int skipdots(char *s, int n)
  38. {
  39.    while (n>0 && s[n]=='/' && s[n-1]=='.' && (n<2 || s[n-2]=='/'))
  40.       n -= 2;
  41.    return n;
  42. }
  43.  
  44. static int unperiod(char *s, int n)
  45. {
  46.    while (n>2 && s[n]=='/' && s[n-1]=='.' && s[n-2]=='.' && s[n-3]=='/') {
  47.       if ((n -= 3) > 0) {
  48.          for (n=nextchar(s, n); n>=0 && s[n]!='/'; n--) ;
  49.       }
  50.    }
  51.    return n;
  52. }
  53.  
  54. static int nextchar(char *s, int n)
  55. {
  56.    if (n >= 0) n -= 1;
  57.  
  58.    while (n>0 && s[n]=='/' && s[n-1]=='.' &&
  59.         ((n<2 || s[n-2]=='/') ||
  60.           n>2 && s[n-2]=='.' && s[n-3]=='/')) {
  61.        if (n>1 && s[n-2]=='.') {
  62.           n = unperiod(s, n);
  63.        } else {
  64.           n = skipdots(s, n);
  65.        }
  66.    }
  67.    return n;
  68. }
  69. #else
  70.     int  strlen();
  71.     char *strcpy(), *strcat(), *strncpy();
  72.     int  open(), read(), close(), unlink();
  73.     long lseek();
  74. #endif
  75. #include "lzpack.h"
  76. #include "roll.h"
  77.  
  78. void cantopen(name)
  79. char *name;
  80. {
  81.    (void)fprintf(myout, "Tar: can\'t open \'%s\'\n", name);
  82. }
  83.  
  84. static void tmpput  __ARGS__(( int ));
  85. static void no_mem  __ARGS__(( int ));
  86. static void errproc __ARGS__(( char * ));
  87.  
  88. static long this;
  89. static infile, ind;
  90.  
  91. static int srcget __ARGS__(( void ))
  92. {
  93.    if (++this > st.st_size) {
  94.       return EOF;
  95. #if 0
  96.       if (this == st.st_size + 1) return EOF;
  97. printf("@");
  98.       /*errproc(hblock->name);*/
  99. #endif
  100.    }
  101.    if (ind >= pksize) {
  102.       if (v_flag) percent(this, st.st_size);
  103.       if (read(infile, pk_inp, pksize) < 1) errproc(hblock->name);
  104.       ind = 0;
  105.    }
  106.    longcsum += ((unsigned char *)pk_inp)[ind];
  107.    return ((unsigned char *)pk_inp)[ind++];
  108. }
  109.  
  110. static void tmpput(c)
  111. int c;
  112. {
  113.    ++codesize; if (rputc(c) != 0) errproc(hblock->name);
  114. }
  115.  
  116. static void no_mem(flag)
  117. int flag;
  118. {
  119.    (void)fprintf(stderr, "No memory for encoding.");
  120.    if (flag) {
  121.       (void)fprintf(stderr, " Continue? ");
  122.       if (YES_NO()) return;
  123.    } else {
  124.       (void)fprintf(stderr, "\n");
  125.    }
  126.    done(ESMALL);
  127. }
  128.  
  129. static void errproc(fname)
  130. char *fname;
  131. {
  132.    (void)fprintf(myout, "\nTar: error processing \'%s\'\n", fname);
  133.    done(EINTER);
  134. }
  135.  
  136. void savefile(fname)
  137. char *fname;
  138. {
  139.    register i; register c;
  140.    register char *p;
  141.    register long blocks;
  142.    register packok;
  143.    register struct node *t; struct node *prev;
  144.  
  145.    p = deleft(fname);
  146.    if (u_flag) {
  147.       if ((t = finditem(p, &prev, timehead)) != NONE) {
  148.          i = t->info.time >= st.st_mtime;
  149.          delitem(t, &timehead);
  150.          if (i) return;
  151.       }
  152.    }
  153.    if (isfile) {/* compare file to store with the archive one */
  154. #ifdef UNIX
  155.       if (st.st_ino == sa.st_ino && st.st_dev == sa.st_dev) return;
  156. #endif
  157. #ifdef MSDOS
  158.       /* The following comparison algorithm may fail */
  159.       /* on combination of substed and real drives   */
  160.       register char *p1, *p2;
  161.       register j1, j2;
  162.       register d2;
  163.       char b[2*MAXPATH];
  164.  
  165.       if (st.st_dev != sa.st_dev) goto next;
  166.  
  167.       /* Sinse 'st_dev' field gives the real drive number */
  168.       /* there is no need to compare drive names          */
  169.  
  170.       j1 = strlen(p1 = archname);
  171.       p2 = fname;
  172.       if (p2[0]>='a' && p2[0]<='z' && p2[1]==':') {
  173.          d2 = p2[0] - ('a'-1);
  174.          p2 += 2;
  175.       } else {
  176.          d2 = 0;
  177.       }
  178.       j2 = strlen(p2);
  179.  
  180.       while (j1>0 && p1[j1-1]!='/' && j2>0 && p2[j2-1]!='/') {
  181.          if (p1[--j1] != p2[--j2]) goto next;
  182.       }
  183.       if (p2[0] != '/') {
  184.          *(int *)b = '/';
  185.          (void)getcurdir(d2, b+1);
  186.          takename(b, b);
  187.          i = strlen(b);
  188.          b[i++] = '/';
  189.          strcpy(b+i, p2);
  190.          p2 = b;
  191.          j2 += i;
  192.       }
  193.       do {
  194.          j1 = nextchar(p1, j1);
  195.          j2 = nextchar(p2, j2);
  196.          if (j1 >= 0 && j2 >= 0 && p1[j1] != p2[j2]) goto next;
  197.       } while (j1>=0 && j2>=0);
  198.       if (j1 == j2) return;
  199. #endif
  200.    }
  201. #ifdef MSDOS
  202. next: i = st.st_mode & 0700; st.st_mode |= (i>>3)|(i>>6);
  203. #endif
  204.    if (w_flag && !okwork('a', ' ', &st, fname)) return;
  205.  
  206.    if ((infile = open(fname, O_RDONLY+O_BINARY)) < 0) {
  207.       cantopen(fname); return;
  208.    }
  209.    newhead(fname, st.st_size);
  210. #ifdef UNIX
  211.    if (st.st_nlink > 1) {
  212.       prev = t = linkhead; i = 1;
  213.       while (t && i>0) {
  214.          i = st.st_ino - t->info.data.inode;
  215.          if (!i) i = st.st_dev - t->info.data.device;
  216.          if (i>0) { prev = t; t = t->next; }
  217.       }
  218.       if (i || !t) {/* entry not found */
  219.          if ((t = additem(p, prev, &linkhead)) == NONE) {
  220.             if (!werelost) {
  221.                (void)fprintf(myout,
  222.                              "Tar: out of memory; link(s) lost\n");
  223.                werelost = TRUE;
  224.             }
  225.          } else {
  226.             t->info.data.count  = st.st_nlink - 1;
  227.             t->info.data.device = st.st_dev;
  228.             t->info.data.inode  = st.st_ino;
  229.          }
  230.       } else {/* previous entry found */
  231.          (void)strncpy(hblock->linkname, t->name, MAXTNAME);
  232.          hblock->filetype = TF_LNK;
  233.          prcsum(hblock);
  234.          if (v_flag) {
  235.             (void)fprintf(myout, "a %s link to %s\n", p, t->name);
  236.          }
  237.          if (--(t->info.data.count) < 1) delitem(t, &linkhead);
  238.          (void)close(infile);
  239.          return;
  240.       }
  241.    }
  242. #endif
  243.    blocks = (st.st_size + (BLKSIZE-1)) / BLKSIZE;
  244.    packok = FALSE;
  245.    if (blocks > 1) {
  246.       if (pktype == PKLZH) {
  247.          if (lzgetmem()!=0 || newroll("TAROLLXXXXXX")!=0) {
  248.             lzrelmem(); delroll();
  249. #ifndef MSDOS
  250.             if (!w_flag) {
  251.                no_mem(0);
  252.             } else
  253. #endif
  254.             {
  255.                no_mem(1);
  256.                pktype = PKNONE;
  257.                goto run;
  258.             }
  259.          }
  260.          (void)rewroll(0);
  261.          longcsum = 0; codesize = 0; this = 0;
  262.          ind = pksize;
  263.          if (v_flag) (void)fprintf(stderr, "e %s", p);
  264.          (void)fflush(stderr);
  265.          if (lzencode(srcget, tmpput) != st.st_size) {
  266.             (void)fprintf(stderr, ": encoding error\n");
  267.             done(EINTER);
  268.          }
  269.       }
  270. #ifdef USE_COMPRESS
  271.       else if (pktype == PKfLZW) {
  272.          if (strlen(hblock->name) > MAXTNAME-2) {
  273. #ifndef MSDOS
  274.             if (!w_flag) {
  275.                (void)fprintf(stderr, longname, hblock->name, "\n");
  276.             } else
  277. #endif
  278.             {
  279.                (void)fprintf(stderr, longname, hblock->name,
  280.                                      " Store uncompressed? ");
  281.                if (YES_NO()) goto run;
  282.             }
  283.             return;
  284.          }
  285.          if (newroll("TAROLLXXXXXX")!=0) {
  286.             delroll();
  287. #ifndef MSDOS
  288.             if (!w_flag) {
  289.                no_mem(0);
  290.             } else
  291. #endif
  292.             {
  293.                no_mem(1);
  294.                pktype = PKNONE;
  295.                goto run;
  296.             }
  297.          }
  298.          if ((i = z_gettab(pklevel)) < pklevel) {
  299.             if (pklevel > 0) {
  300. #ifndef MSDOS
  301.                if (!w_flag) {
  302.                   (void)fprintf(stderr, "Can only handle %d bits.\n", i);
  303.                } else
  304. #endif
  305.                {
  306.                   (void)fprintf(stderr,
  307.                            "Can only handle %d bits. Continue? ", i);
  308.                   pklevel = YES_NO() ? i : -1;
  309.                }
  310.             }
  311.             if (pklevel <= 0) {
  312.